#region License, Terms and Conditions
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using pesta.Data;
using Pesta.DataAccess.SqlServer;
using Pesta.Utilities.Helpers;
using Pesta.DataAccess.Azure;
using raya.Library;

namespace raya.Models.messages
{
    public class MessageRaya
    {
        public Message msg { get; set; }
        // additional fields unique to raya
        public string recipient { get; set; }
        public string name { get; set; }
        public string thumbnail { get; set; }
        public string read { get; set; }
    }
    public class MessagesProfile
    {
        public List<MessageRaya> messages { get; set; }
        public string type { get; set; }
    }

    public class MessageProfile
    {
        public MessageRaya message { get; set; }
        public string msgtype { get; set; }
        public string msgid { get; set; }
    }

    public class messages : Model
    {
#if AZURE
        public void send_message(string sender, string recipient, string subject, string body)
        {
            using (var db = RayaDataContext.DB())
            {
                var time = DateTime.UtcNow;
                var msg = new MessageRow(sender, time.Ticks.ToString())
                              {
                                  sender = sender,
                                  recipient = recipient,
                                  title = subject,
                                  body = body,
                                  created = time.ToUnixTime(),
                                  read = "no",
                                  to_deleted = "no",
                                  from_deleted = "no"
                              };
                db.InsertOnSubmit(AzureRayaDataContext.TableNames.messages, msg);
                db.SubmitChanges();
            }
        }

        public void delete_message(string messageId, string toOrFrom)
        {
            using (var db = RayaDataContext.DB())
            {
                var msg = db.messages.Where(x => x.RowKey == messageId).SingleOrDefault();
                if (msg != null)
                {
                    if (toOrFrom == "to")
                    {
                        msg.to_deleted = "yes";
                    }
                    else if (toOrFrom == "from")
                    {
                        msg.from_deleted = "yes";
                    }
                    else
                    {
                        throw new Exception("eeek!");
                    }
                    db.UpdateOnSubmit(msg);
                    db.SubmitChanges();
                }
            }
        }
        public MessageRaya get_message(string messageId)
        {
            return get_message(messageId, "inbox");
        }

        public MessageRaya get_message(string messageId, string type)
        {
            if (type != "inbox" && type != "sent")
            {
                throw new Exception("unknown message type");
            }
            using (var db = RayaDataContext.DB())
            {
                if (type == "inbox")
                {
                    var res = db.messages.Where(m => m.RowKey == messageId).SingleOrDefault();
                    if (res != null)
                    {
                        MessageRaya msgRaya = new MessageRaya()
                        {
                            msg = res.ToModel(),
                            recipient = res.recipient,
                            name = res.senderName,
                            thumbnail = res.senderThumbnailUrl,
                            read = res.read
                        };
                        return msgRaya;
                    }
                }
                else
                {

                    var res = db.messages.Where(m => m.id == messageId).SingleOrDefault();
                    if (res != null)
                    {
                        MessageRaya msgRaya = new MessageRaya()
                        {
                            msg = res.ToModel(),
                            recipient = res.recipient,
                            name = res.recipientName,
                            thumbnail = res.recipientThumbnailUrl
                        };
                        return msgRaya;
                    }
                }
            }
            return null;
        }

        public void mark_read(string messageId)
        {
            using (var db = RayaDataContext.DB())
            {
                var res = db.messages.Where(m => m.id == messageId).SingleOrDefault();
                if (res != null)
                {
                    res.read = "yes";
                    db.UpdateOnSubmit(res);
                    db.SubmitChanges();
                }
            }
        }
        public List<MessageRaya> get_inbox(string userId)
        {
            return get_inbox(userId, 0, 20);
        }

        public List<MessageRaya> get_inbox(string userId, int start, int count)
        {
            var msgs = new List<MessageRaya>();
            using (var db = RayaDataContext.DB())
            {
                var res = db.messages.Where(m => m.recipient == userId && m.to_deleted == "no");
                foreach (var m in res)
                {
                    var msgRaya = new MessageRaya()
                                      {
                                          msg = m.ToModel(),
                                          recipient = m.recipient,
                                          name = m.recipientName,
                                          thumbnail = m.recipientThumbnailUrl,
                                          read = m.read
                                      };
                    msgs.Add(msgRaya);
                }
                // order
                IEnumerable<MessageRaya> ordered = msgs.OrderByDescending(x => x.msg.timeSent);
                
                // skip
                ordered = ordered.Skip(start);

                // take
                if (count != 0)
                {
                    ordered = ordered.Take(count);
                }
                return ordered.ToList();
            }
        }

        public List<MessageRaya> get_sent(string userId)
        {
            return get_sent(userId, 0, 20);
        }
        public List<MessageRaya> get_sent(string userId, int start, int count)
        {
            var msgs = new List<MessageRaya>();
            using (var db = RayaDataContext.DB())
            {
                var res = db.messages.Where(m => m.sender == userId && m.from_deleted == "no");
                foreach (var m in res)
                {
                    var msgRaya = new MessageRaya()
                    {
                        msg = m.ToModel(),
                        recipient = m.recipient,
                        name = m.senderName,
                        thumbnail = m.senderThumbnailUrl,
                        read = m.read
                    };
                    msgs.Add(msgRaya);
                }
                // order
                IEnumerable<MessageRaya> ordered = msgs.OrderByDescending(x => x.msg.timeSent);

                // skip
                ordered = ordered.Skip(start);

                // take
                if (count != 0)
                {
                    ordered = ordered.Take(count);
                }
                return ordered.ToList();
            }
        }
#else
        public void send_message(string sender, string recipient, string _subject, string _body) 
        {
            int from = int.Parse(sender);
            using (var db = RayaDataContext.DB())
            {
                var msg = new message();
                msg.sender = from;
                msg.recipient = int.Parse(recipient);
                msg.title = _subject;
                msg.body = _body;
                msg.created = DateTime.UtcNow.ToUnixTime();
                msg.read = "no";
                msg.to_deleted = "no";
                msg.from_deleted = "no";
                db.messages.InsertOnSubmit(msg);
                db.SubmitChanges();
            }
        }

        public void delete_message(string _message_id, string _to_or_from) 
        {
            int message_id = int.Parse(_message_id);
            using (var db = RayaDataContext.DB())
            {
                var msg = db.messages.Where(x => x.id == message_id).Single();
                if (_to_or_from == "to") 
                {
                    msg.to_deleted = "yes";
                } 
                else if (_to_or_from == "from")
                {
                    msg.from_deleted = "yes";
                } 
                else 
                {
                    throw new Exception("eeek!");
                }
                db.SubmitChanges();
            }
        }
        public MessageRaya get_message(string _message_id)
        {
            return get_message(_message_id, "inbox");
        }

        public MessageRaya get_message(string _message_id, string _type) 
        {
            int message_id = int.Parse(_message_id);
            if (_type != "inbox" && _type != "sent") 
            {
                throw new Exception("unknown message type");
            }
            using (var db = RayaDataContext.DB())
            {
                if (_type == "inbox")
                {
                    var res = db.messages.Where(m => m.id == message_id)
                        .Join(db.persons, m => m.sender, p => p.id, (m, p) => new {m, p})
                        .Select(x => new MessageRaya()
                        { 
                            msg = new Message()
                                      {
                                         id = x.m.id.ToString(),
                                        senderId = x.m.sender.ToString(),
                                   body = x.m.body,
                                   title = x.m.title,
                                   timeSent = x.m.created.FromUnixTime()
                                      },
                            recipient = x.m.recipient.ToString(),
                            name = x.p.first_name + " " + x.p.last_name,
                            thumbnail = x.p.thumbnail_url,
                            read = x.m.read
                        }
                        );
                    return res.SingleOrDefault();
                }
                else
                {
                    
                    var res = db.messages.Where(m => m.id == message_id)
                        .Join(db.persons, m => m.recipient.ToString(), p => p.id.ToString(), (m, p) => new { m, p })
                        .Select(x => new MessageRaya()
                        {
                            msg = new Message()
                                      {
                                          id = x.m.id.ToString(), 
                                          senderId = x.m.sender.ToString(),
                                          body = x.m.body,
                                          title = x.m.title,
                                          timeSent = x.m.created.FromUnixTime()
                                      },
                            recipient = x.m.recipient.ToString(),
                            name = x.p.first_name + " " + x.p.last_name,
                            thumbnail = x.p.thumbnail_url
                        }
                        ); 
                    return res.SingleOrDefault();
                }
            }
        }

        public void mark_read(string _message_id) 
        {
            int message_id = int.Parse(_message_id);
            using (var db = RayaDataContext.DB())
            {
                var res = db.messages.Where(m => m.id == message_id).SingleOrDefault();
                res.read = "yes";
                db.SubmitChanges();
            }
        }
        public List<MessageRaya> get_inbox(string userId)
        {
            return get_inbox(userId, 0, 20);
        }

        public List<MessageRaya> get_inbox(string uid, int start, int count) 
        {
            int userId = int.Parse(uid);
            using (var db = RayaDataContext.DB())
            {
                var res = (from m in db.messages
                           where m.recipient == userId && m.to_deleted == "no"
                           from p in db.persons
                           where m.sender == p.id
                           orderby m.created descending 
                           select new MessageRaya()
                                      {
                                          msg = new Message()
                                                    {
                                                       id = m.id.ToString(),
                                                       senderId = m.sender.ToString(),
                                                       body = m.body,
                                                       title = m.title,
                                                       timeSent = m.created.FromUnixTime()
                                                    },
                                                    recipient = m.recipient.ToString(),
                                          name = p.first_name + " " + p.last_name,
                                          thumbnail = p.thumbnail_url,
                                          read = m.read
                                      }).Skip(start);
                if (count != 0)
                {
                    res = res.Take(count);
                }
                return res.ToList();
            }
        }

        public List<MessageRaya> get_sent(string userId)
        {
            return get_sent(userId, 0, 20);
        }
        public List<MessageRaya> get_sent(string uid, int start, int count) 
        {
            int userId = int.Parse(uid);
            using (var db = RayaDataContext.DB())
            {
                var res = (from m in db.messages
                           where m.sender == userId && m.to_deleted == "no"
                           from p in db.persons
                           where m.recipient == p.id
                           orderby m.created descending
                           select new MessageRaya()
                                      {
                                          msg = new Message()
                                                    {
                                                        id = m.id.ToString(), 
                                                        senderId = m.sender.ToString(), 
                                                        body = m.body,
                                                        title = m.title,
                                                        timeSent = m.created.FromUnixTime()
                                                    },
                                          recipient = m.recipient.ToString(),
                              name = p.first_name + " " + p.last_name,
                              thumbnail = p.thumbnail_url
                          }).Skip(start);

                if (count != 0)
                {
                    res = res.Take(count);
                }
                return res.ToList();
            }
        }
#endif


    }
}